package version

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"sync"

	"github.com/Masterminds/semver/v3"
)

// PluginMetadata 表示插件元数据
type PluginMetadata struct {
	// ID 是插件ID
	ID string `json:"id"`
	// Name 是插件名称
	Name string `json:"name"`
	// Version 是插件版本
	Version string `json:"version"`
	// Description 是插件描述
	Description string `json:"description"`
	// Author 是插件作者
	Author string `json:"author"`
	// License 是插件许可证
	License string `json:"license"`
	// Dependencies 是插件依赖
	Dependencies map[string]string `json:"dependencies"`
	// EntryPoint 是插件入口点
	EntryPoint string `json:"entryPoint"`
	// Tags 是插件标签
	Tags []string `json:"tags"`
	// TargetPlatforms 是目标平台
	TargetPlatforms []string `json:"targetPlatforms"`
	// MinHostVersion 是最小主机版本
	MinHostVersion string `json:"minHostVersion"`
	// MaxHostVersion 是最大主机版本
	MaxHostVersion string `json:"maxHostVersion"`
	// PluginAPIVersion 是插件API版本
	PluginAPIVersion string `json:"pluginApiVersion"`
	// FilePath 是插件文件路径
	FilePath string `json:"-"`
}

// PluginVersionConstraint 表示插件版本约束
type PluginVersionConstraint struct {
	// ID 是插件ID
	ID string
	// Constraint 是版本约束
	Constraint string
}

// PluginVersionManager 表示插件版本管理器
type PluginVersionManager struct {
	// pluginsDir 是插件目录
	pluginsDir string
	// metadataDir 是元数据目录
	metadataDir string
	// plugins 是插件映射表
	plugins map[string][]*PluginMetadata
	// activeVersions 是活动版本映射表
	activeVersions map[string]string
	// hostVersion 是主机版本
	hostVersion *semver.Version
	// pluginAPIVersion 是插件API版本
	pluginAPIVersion *semver.Version
	// mu 是互斥锁
	mu sync.RWMutex
}

// NewPluginVersionManager 创建一个新的插件版本管理器
func NewPluginVersionManager(pluginsDir, metadataDir, hostVersion, pluginAPIVersion string) (*PluginVersionManager, error) {
	// 解析主机版本
	hv, err := semver.NewVersion(hostVersion)
	if err != nil {
		return nil, fmt.Errorf("invalid host version: %w", err)
	}

	// 解析插件API版本
	pv, err := semver.NewVersion(pluginAPIVersion)
	if err != nil {
		return nil, fmt.Errorf("invalid plugin API version: %w", err)
	}

	return &PluginVersionManager{
		pluginsDir:      pluginsDir,
		metadataDir:     metadataDir,
		plugins:         make(map[string][]*PluginMetadata),
		activeVersions:  make(map[string]string),
		hostVersion:     hv,
		pluginAPIVersion: pv,
	}, nil
}

// Initialize 初始化插件版本管理器
func (m *PluginVersionManager) Initialize() error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// 确保目录存在
	err := os.MkdirAll(m.pluginsDir, 0755)
	if err != nil {
		return fmt.Errorf("failed to create plugins directory: %w", err)
	}

	err = os.MkdirAll(m.metadataDir, 0755)
	if err != nil {
		return fmt.Errorf("failed to create metadata directory: %w", err)
	}

	// 加载插件元数据
	err = m.loadPluginMetadata()
	if err != nil {
		return fmt.Errorf("failed to load plugin metadata: %w", err)
	}

	// 加载活动版本
	err = m.loadActiveVersions()
	if err != nil {
		return fmt.Errorf("failed to load active versions: %w", err)
	}

	return nil
}

// RegisterPlugin 注册插件
func (m *PluginVersionManager) RegisterPlugin(metadata *PluginMetadata) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// 验证插件元数据
	err := m.validatePluginMetadata(metadata)
	if err != nil {
		return fmt.Errorf("invalid plugin metadata: %w", err)
	}

	// 检查插件是否已存在
	versions, ok := m.plugins[metadata.ID]
	if !ok {
		versions = make([]*PluginMetadata, 0)
	}

	// 检查版本是否已存在
	for _, v := range versions {
		if v.Version == metadata.Version {
			return fmt.Errorf("plugin %s version %s already exists", metadata.ID, metadata.Version)
		}
	}

	// 添加插件
	versions = append(versions, metadata)
	m.plugins[metadata.ID] = versions

	// 保存元数据
	err = m.savePluginMetadata(metadata)
	if err != nil {
		return fmt.Errorf("failed to save plugin metadata: %w", err)
	}

	// 如果没有活动版本，设置为活动版本
	if _, ok := m.activeVersions[metadata.ID]; !ok {
		m.activeVersions[metadata.ID] = metadata.Version
		err = m.saveActiveVersions()
		if err != nil {
			return fmt.Errorf("failed to save active versions: %w", err)
		}
	}

	return nil
}

// UnregisterPlugin 注销插件
func (m *PluginVersionManager) UnregisterPlugin(id, version string) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// 检查插件是否存在
	versions, ok := m.plugins[id]
	if !ok {
		return fmt.Errorf("plugin %s not found", id)
	}

	// 查找版本
	index := -1
	for i, v := range versions {
		if v.Version == version {
			index = i
			break
		}
	}

	if index == -1 {
		return fmt.Errorf("plugin %s version %s not found", id, version)
	}

	// 检查是否是活动版本
	if activeVersion, ok := m.activeVersions[id]; ok && activeVersion == version {
		// 如果只有一个版本，删除活动版本
		if len(versions) == 1 {
			delete(m.activeVersions, id)
		} else {
			// 否则，选择最新版本作为活动版本
			var newActiveVersion string
			for _, v := range versions {
				if v.Version != version {
					newActiveVersion = v.Version
					break
				}
			}
			m.activeVersions[id] = newActiveVersion
		}

		// 保存活动版本
		err := m.saveActiveVersions()
		if err != nil {
			return fmt.Errorf("failed to save active versions: %w", err)
		}
	}

	// 删除元数据文件
	metadataPath := filepath.Join(m.metadataDir, fmt.Sprintf("%s-%s.json", id, version))
	err := os.Remove(metadataPath)
	if err != nil && !os.IsNotExist(err) {
		return fmt.Errorf("failed to remove metadata file: %w", err)
	}

	// 删除插件
	m.plugins[id] = append(versions[:index], versions[index+1:]...)
	if len(m.plugins[id]) == 0 {
		delete(m.plugins, id)
	}

	return nil
}

// GetPlugin 获取插件
func (m *PluginVersionManager) GetPlugin(id, version string) (*PluginMetadata, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	// 检查插件是否存在
	versions, ok := m.plugins[id]
	if !ok {
		return nil, fmt.Errorf("plugin %s not found", id)
	}

	// 如果版本为空，返回活动版本
	if version == "" {
		activeVersion, ok := m.activeVersions[id]
		if !ok {
			return nil, fmt.Errorf("no active version for plugin %s", id)
		}
		version = activeVersion
	}

	// 查找版本
	for _, v := range versions {
		if v.Version == version {
			return v, nil
		}
	}

	return nil, fmt.Errorf("plugin %s version %s not found", id, version)
}

// GetAllPlugins 获取所有插件
func (m *PluginVersionManager) GetAllPlugins() map[string][]*PluginMetadata {
	m.mu.RLock()
	defer m.mu.RUnlock()

	// 复制插件映射表
	plugins := make(map[string][]*PluginMetadata)
	for id, versions := range m.plugins {
		plugins[id] = make([]*PluginMetadata, len(versions))
		copy(plugins[id], versions)
	}

	return plugins
}

// GetActiveVersion 获取活动版本
func (m *PluginVersionManager) GetActiveVersion(id string) (string, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	// 检查插件是否存在
	if _, ok := m.plugins[id]; !ok {
		return "", fmt.Errorf("plugin %s not found", id)
	}

	// 获取活动版本
	version, ok := m.activeVersions[id]
	if !ok {
		return "", fmt.Errorf("no active version for plugin %s", id)
	}

	return version, nil
}

// SetActiveVersion 设置活动版本
func (m *PluginVersionManager) SetActiveVersion(id, version string) error {
	m.mu.Lock()
	defer m.mu.Unlock()

	// 检查插件是否存在
	versions, ok := m.plugins[id]
	if !ok {
		return fmt.Errorf("plugin %s not found", id)
	}

	// 检查版本是否存在
	found := false
	for _, v := range versions {
		if v.Version == version {
			found = true
			break
		}
	}

	if !found {
		return fmt.Errorf("plugin %s version %s not found", id, version)
	}

	// 设置活动版本
	m.activeVersions[id] = version

	// 保存活动版本
	err := m.saveActiveVersions()
	if err != nil {
		return fmt.Errorf("failed to save active versions: %w", err)
	}

	return nil
}

// GetLatestVersion 获取最新版本
func (m *PluginVersionManager) GetLatestVersion(id string) (string, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	// 检查插件是否存在
	versions, ok := m.plugins[id]
	if !ok {
		return "", fmt.Errorf("plugin %s not found", id)
	}

	if len(versions) == 0 {
		return "", fmt.Errorf("no versions found for plugin %s", id)
	}

	// 解析版本
	semvers := make([]*semver.Version, len(versions))
	versionMap := make(map[string]*PluginMetadata)
	for i, v := range versions {
		sv, err := semver.NewVersion(v.Version)
		if err != nil {
			return "", fmt.Errorf("invalid version %s for plugin %s: %w", v.Version, id, err)
		}
		semvers[i] = sv
		versionMap[sv.String()] = v
	}

	// 排序版本
	sort.Sort(sort.Reverse(semver.Collection(semvers)))

	// 返回最新版本
	return semvers[0].String(), nil
}

// ResolveVersionConstraint 解析版本约束
func (m *PluginVersionManager) ResolveVersionConstraint(id, constraint string) (string, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	// 检查插件是否存在
	versions, ok := m.plugins[id]
	if !ok {
		return "", fmt.Errorf("plugin %s not found", id)
	}

	if len(versions) == 0 {
		return "", fmt.Errorf("no versions found for plugin %s", id)
	}

	// 解析约束
	c, err := semver.NewConstraint(constraint)
	if err != nil {
		return "", fmt.Errorf("invalid constraint %s: %w", constraint, err)
	}

	// 解析版本
	semvers := make([]*semver.Version, 0)
	versionMap := make(map[string]*PluginMetadata)
	for _, v := range versions {
		sv, err := semver.NewVersion(v.Version)
		if err != nil {
			return "", fmt.Errorf("invalid version %s for plugin %s: %w", v.Version, id, err)
		}
		// 检查约束
		if c.Check(sv) {
			semvers = append(semvers, sv)
			versionMap[sv.String()] = v
		}
	}

	if len(semvers) == 0 {
		return "", fmt.Errorf("no version satisfies constraint %s for plugin %s", constraint, id)
	}

	// 排序版本
	sort.Sort(sort.Reverse(semver.Collection(semvers)))

	// 返回最新版本
	return semvers[0].String(), nil
}

// ResolveDependencies 解析依赖
func (m *PluginVersionManager) ResolveDependencies(id, version string) (map[string]string, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	// 获取插件
	plugin, err := m.GetPlugin(id, version)
	if err != nil {
		return nil, fmt.Errorf("failed to get plugin: %w", err)
	}

	// 解析依赖
	resolved := make(map[string]string)
	for depID, constraint := range plugin.Dependencies {
		version, err := m.ResolveVersionConstraint(depID, constraint)
		if err != nil {
			return nil, fmt.Errorf("failed to resolve dependency %s: %w", depID, err)
		}
		resolved[depID] = version
	}

	return resolved, nil
}

// validatePluginMetadata 验证插件元数据
func (m *PluginVersionManager) validatePluginMetadata(metadata *PluginMetadata) error {
	// 检查必填字段
	if metadata.ID == "" {
		return errors.New("plugin ID is required")
	}
	if metadata.Name == "" {
		return errors.New("plugin name is required")
	}
	if metadata.Version == "" {
		return errors.New("plugin version is required")
	}
	if metadata.EntryPoint == "" {
		return errors.New("plugin entry point is required")
	}

	// 验证版本格式
	_, err := semver.NewVersion(metadata.Version)
	if err != nil {
		return fmt.Errorf("invalid version format: %w", err)
	}

	// 验证主机版本约束
	if metadata.MinHostVersion != "" {
		c, err := semver.NewConstraint(">=" + metadata.MinHostVersion)
		if err != nil {
			return fmt.Errorf("invalid min host version: %w", err)
		}
		if !c.Check(m.hostVersion) {
			return fmt.Errorf("plugin requires host version >= %s, but current is %s", metadata.MinHostVersion, m.hostVersion)
		}
	}

	if metadata.MaxHostVersion != "" {
		c, err := semver.NewConstraint("<=" + metadata.MaxHostVersion)
		if err != nil {
			return fmt.Errorf("invalid max host version: %w", err)
		}
		if !c.Check(m.hostVersion) {
			return fmt.Errorf("plugin requires host version <= %s, but current is %s", metadata.MaxHostVersion, m.hostVersion)
		}
	}

	// 验证插件API版本
	if metadata.PluginAPIVersion != "" {
		c, err := semver.NewConstraint(metadata.PluginAPIVersion)
		if err != nil {
			return fmt.Errorf("invalid plugin API version: %w", err)
		}
		if !c.Check(m.pluginAPIVersion) {
			return fmt.Errorf("plugin requires API version %s, but current is %s", metadata.PluginAPIVersion, m.pluginAPIVersion)
		}
	}

	// 验证依赖
	for depID, constraint := range metadata.Dependencies {
		_, err := m.ResolveVersionConstraint(depID, constraint)
		if err != nil {
			return fmt.Errorf("failed to resolve dependency %s: %w", depID, err)
		}
	}

	return nil
}

// loadPluginMetadata 加载插件元数据
func (m *PluginVersionManager) loadPluginMetadata() error {
	// 读取元数据目录
	entries, err := os.ReadDir(m.metadataDir)
	if err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return fmt.Errorf("failed to read metadata directory: %w", err)
	}

	// 加载所有元数据文件
	for _, entry := range entries {
		if entry.IsDir() {
			continue
		}

		// 检查文件扩展名
		if filepath.Ext(entry.Name()) != ".json" {
			continue
		}

		// 读取元数据文件
		path := filepath.Join(m.metadataDir, entry.Name())
		data, err := ioutil.ReadFile(path)
		if err != nil {
			return fmt.Errorf("failed to read metadata file %s: %w", path, err)
		}

		// 解析元数据
		var metadata PluginMetadata
		err = json.Unmarshal(data, &metadata)
		if err != nil {
			return fmt.Errorf("failed to parse metadata file %s: %w", path, err)
		}

		// 设置文件路径
		parts := strings.Split(entry.Name(), "-")
		if len(parts) < 2 {
			return fmt.Errorf("invalid metadata file name %s", entry.Name())
		}
		version := strings.TrimSuffix(parts[len(parts)-1], ".json")
		metadata.FilePath = filepath.Join(m.pluginsDir, fmt.Sprintf("%s-%s.so", metadata.ID, version))

		// 添加插件
		versions, ok := m.plugins[metadata.ID]
		if !ok {
			versions = make([]*PluginMetadata, 0)
		}
		versions = append(versions, &metadata)
		m.plugins[metadata.ID] = versions
	}

	return nil
}

// savePluginMetadata 保存插件元数据
func (m *PluginVersionManager) savePluginMetadata(metadata *PluginMetadata) error {
	// 创建元数据文件路径
	path := filepath.Join(m.metadataDir, fmt.Sprintf("%s-%s.json", metadata.ID, metadata.Version))

	// 序列化元数据
	data, err := json.MarshalIndent(metadata, "", "  ")
	if err != nil {
		return fmt.Errorf("failed to serialize metadata: %w", err)
	}

	// 写入文件
	err = ioutil.WriteFile(path, data, 0644)
	if err != nil {
		return fmt.Errorf("failed to write metadata file: %w", err)
	}

	return nil
}

// loadActiveVersions 加载活动版本
func (m *PluginVersionManager) loadActiveVersions() error {
	// 创建活动版本文件路径
	path := filepath.Join(m.metadataDir, "active-versions.json")

	// 检查文件是否存在
	_, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return fmt.Errorf("failed to stat active versions file: %w", err)
	}

	// 读取文件
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return fmt.Errorf("failed to read active versions file: %w", err)
	}

	// 解析数据
	err = json.Unmarshal(data, &m.activeVersions)
	if err != nil {
		return fmt.Errorf("failed to parse active versions file: %w", err)
	}

	return nil
}

// saveActiveVersions 保存活动版本
func (m *PluginVersionManager) saveActiveVersions() error {
	// 创建活动版本文件路径
	path := filepath.Join(m.metadataDir, "active-versions.json")

	// 序列化数据
	data, err := json.MarshalIndent(m.activeVersions, "", "  ")
	if err != nil {
		return fmt.Errorf("failed to serialize active versions: %w", err)
	}

	// 写入文件
	err = ioutil.WriteFile(path, data, 0644)
	if err != nil {
		return fmt.Errorf("failed to write active versions file: %w", err)
	}

	return nil
}
